using TerritoryGame.Domain.Common;
using TerritoryGame.Domain.Enums;
using TerritoryGame.Domain.Events;
using TerritoryGame.Domain.Exceptions;
using TerritoryGame.Domain.ValueObjects;

namespace TerritoryGame.Domain.Entities;

/// <summary>
/// 游戏聚合根 - 管理游戏生命周期和规则
/// </summary>
public class Game : AggregateRoot<GameId>
{
    public GameName Name { get; private set; }
    public GameStatus Status { get; private set; }
    public GameDuration Duration { get; private set; }
    public DateTime? StartTime { get; private set; }
    public DateTime? EndTime { get; private set; }
    public Canvas Canvas { get; private set; }
    
    private readonly List<Player> _players = new();
    private readonly List<IDomainEvent> _domainEvents = new();
    
    public IReadOnlyList<Player> Players => _players.AsReadOnly();
    
    // EF Core 构造函数
    private Game() { }
    
    public Game(GameId id, GameName name, GameDuration duration)
    {
        Id = id;
        Name = name;
        Duration = duration;
        Status = GameStatus.Waiting;
        Canvas = new Canvas();
        
        AddDomainEvent(new GameCreatedEvent(Id, Name));
    }
    
    /// <summary>
    /// 添加玩家到游戏
    /// </summary>
    public void AddPlayer(Player player)
    {
        if (_players.Count >= 6)
            throw new DomainException("游戏房间已满，最多支持6名玩家");
            
        if (_players.Any(p => p.Id == player.Id))
            throw new DomainException("玩家已在游戏中");
            
        _players.Add(player);
        AddDomainEvent(new PlayerJoinedEvent(Id, player.Id, player.Nickname));
    }
    
    /// <summary>
    /// 移除玩家
    /// </summary>
    public void RemovePlayer(PlayerId playerId)
    {
        var player = _players.FirstOrDefault(p => p.Id == playerId);
        if (player == null)
            throw new DomainException("玩家不在游戏中");
            
        _players.Remove(player);
        AddDomainEvent(new PlayerLeftEvent(Id, playerId, player.Nickname));
        
        // 如果玩家数量不足，结束游戏
        if (_players.Count < 2 && Status == GameStatus.Playing)
        {
            EndGame();
        }
    }
    
    /// <summary>
    /// 开始游戏
    /// </summary>
    public void StartGame()
    {
        if (_players.Count < 2)
            throw new DomainException("至少需要2名玩家才能开始游戏");
            
        if (Status != GameStatus.Waiting)
            throw new DomainException("游戏状态不允许开始");
            
        Status = GameStatus.Playing;
        StartTime = DateTime.UtcNow;
        
        // 为玩家分配颜色
        AssignPlayerColors();
        
        AddDomainEvent(new GameStartedEvent(Id, Players, Duration));
    }
    
    /// <summary>
    /// 结束游戏
    /// </summary>
    public void EndGame()
    {
        if (Status != GameStatus.Playing)
            throw new DomainException("游戏状态不允许结束");
            
        Status = GameStatus.Finished;
        EndTime = DateTime.UtcNow;
        
        // 计算最终结果
        var results = CalculateFinalResults();
        
        AddDomainEvent(new GameEndedEvent(Id, results));
    }
    
    /// <summary>
    /// 处理涂色动作
    /// </summary>
    public void ProcessPaintAction(PlayerId playerId, Position position, BrushSize brushSize)
    {
        if (Status != GameStatus.Playing)
            throw new DomainException("游戏未开始，无法涂色");
            
        var player = GetPlayer(playerId);
        if (player == null)
            throw new DomainException("玩家不在游戏中");
            
        // 检查是否可以在此位置绘制
        if (!Canvas.CanPaintAt(position, player.Color))
            throw new DomainException("无法在此位置绘制");
            
        // 执行涂色
        Canvas.Paint(position, player.Color, brushSize);
        
        // 更新玩家面积
        UpdatePlayerArea(playerId);
        
        AddDomainEvent(new AreaCapturedEvent(Id, playerId, position, brushSize));
    }
    
    /// <summary>
    /// 获取玩家
    /// </summary>
    private Player? GetPlayer(PlayerId playerId)
    {
        return _players.FirstOrDefault(p => p.Id == playerId);
    }
    
    /// <summary>
    /// 为玩家分配颜色
    /// </summary>
    private void AssignPlayerColors()
    {
        var colors = new[] 
        {
            PlayerColor.Red, PlayerColor.Blue, PlayerColor.Green,
            PlayerColor.Yellow, PlayerColor.Purple, PlayerColor.Orange
        };
        
        for (int i = 0; i < _players.Count; i++)
        {
            _players[i].AssignColor(colors[i]);
        }
    }
    
    /// <summary>
    /// 更新玩家面积
    /// </summary>
    private void UpdatePlayerArea(PlayerId playerId)
    {
        var player = GetPlayer(playerId);
        if (player == null) return;
        
        var area = Canvas.CalculateAreaByColor(player.Color);
        player.UpdateArea(area);
    }
    
    /// <summary>
    /// 计算最终结果
    /// </summary>
    private List<GameResult> CalculateFinalResults()
    {
        var results = _players
            .Select(p => new GameResult(p.Id, p.Nickname, p.Color, p.Area))
            .OrderByDescending(r => r.Area)
            .ToList();
            
        // 设置排名
        for (int i = 0; i < results.Count; i++)
        {
            results[i].SetRank(i + 1);
        }
        
        return results;
    }
    
    /// <summary>
    /// 添加领域事件
    /// </summary>
    private void AddDomainEvent(IDomainEvent domainEvent)
    {
        _domainEvents.Add(domainEvent);
    }
    
    /// <summary>
    /// 获取领域事件
    /// </summary>
    public IReadOnlyList<IDomainEvent> GetDomainEvents()
    {
        var events = _domainEvents.ToList();
        _domainEvents.Clear();
        return events;
    }
}
